home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DDJMAG
/
DDJ9207.ZIP
/
ACOMP.ZIP
/
UNC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-14
|
7KB
|
191 lines
#include "uc.h"
/*****************************************************************************/
/* UNC.C This is the C version of the ACOMP decompressor. Compare it to */
/* the assembly language version of the same, in UC.ASM. The */
/* assembly version of the decompressor is 2.4 times faster than the */
/* C version. Probabably some hand optimization of either would */
/* change these statistics. */
/* It is very imporant to note that you could deburst this algorithm */
/* so that it could decompress portions of the audio, as a background*/
/* task, thus allowing you to play back and decompress digitized */
/* sound, simultaneously! This would allow you to play back large */
/* digitized sound samples while using a very limited amount of core */
/* memory. The UCOMP decompressor could easily be put into a */
/* hardware based system, and it's performance characteristics far */
/* exceed current hardware based audio decompression systems such as */
/* CVSD and LPC encoding. */
/* To give you some performance characteristics look at the following*/
/* On my 20mhz 386 system, it took 0.1141 seconds to decompress 58k */
/* of audio. (0.3451 seconds using the C version.) That comes */
/* out to 600k per second! The amount of CPU overhead to */
/* decompress the audio, as it is played back, is truely */
/* negligible. */
/*****************************************************************************/
#define SQLCH 0x40 // Squelch byte flag
#define RESYNC 0x80 // Resync byte flag.
#define DELTAMOD 0x30 // Delta modulation bits.
#define ONEBIT 0x10 // One bit delta modulate
#define TWOBIT 0x20 // Two bit delta modulate
#define FOURBIT 0x30 // four bit delta modulate
#define MULTIPLIER 0x0F // Bottom nibble contains multiplier value.
#define SQUELCHCNT 0x3F // Bits for squelching.
static signed char trans[16*16] =
{
-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8, // Multiplier of 1
-16,-14,-12,-10,-8,-6,-4,-2,2,4,6,8,10,12,14,16, // Multiplier of 2
-24,-21,-18,-15,-12,-9,-6,-3,3,6,9,12,15,18,21,24, // Multiplier of 3
-32,-28,-24,-20,-16,-12,-8,-4,4,8,12,16,20,24,28,32, // Multiplier of 4
-40,-35,-30,-25,-20,-15,-10,-5,5,10,15,20,25,30,35,40, // Multiplier of 5
-48,-42,-36,-30,-24,-18,-12,-6,6,12,18,24,30,36,42,48, // Multiplier of 6
-56,-49,-42,-35,-28,-21,-14,-7,7,14,21,28,35,42,49,56, // Multiplier of 7
-64,-56,-48,-40,-32,-24,-16,-8,8,16,24,32,40,48,56,64, // Multiplier of 8
-72,-63,-54,-45,-36,-27,-18,-9,9,18,27,36,45,54,63,72, // Multiplier of 9
-80,-70,-60,-50,-40,-30,-20,-10,10,20,30,40,50,60,70,80, // Multiplier of 10
-88,-77,-66,-55,-44,-33,-22,-11,11,22,33,44,55,66,77,88, // Multiplier of 11
-96,-84,-72,-60,-48,-36,-24,-12,12,24,36,48,60,72,84,96, // Multiplier of 12
-104,-91,-78,-65,-52,-39,-26,-13,13,26,39,52,65,78,91,104, // Multiplier of 13
-112,-98,-84,-70,-56,-42,-28,-14,14,28,42,56,70,84,98,112, // Multiplier of 14
-120,-105,-90,-75,-60,-45,-30,-15,15,30,45,60,75,90,105,120, // Multiplier of 15
-127,-112,-96,-80,-64,-48,-32,-16,16,32,48,64,80,96,112,127 }; // Multiplier of 16
short Get8086word(unsigned char far *temp);
// UnCompressAudio will decompress data which was compressed using ACOMP
// into the destination address provided. UnCompressAudio returns the
// total size, in bytes, of the uncompressed audio data.
unsigned int far UnCompressAudio(unsigned char far *source,unsigned char far *dest)
{
unsigned short slen,frame,bits,count,length,plier,bytes;
unsigned char sample,mask;
short prev,up,down,one,two,three,four;
signed char *base;
slen = length = Get8086word(source);
source+=4; // Skip length, and then frequency word.
frame = *source++; // Frame size.
source+=3; // Skip sqelch value, and maximum error allowed.
prev = *dest++ = *source++; // Get initial previous data point.
slen--; // Decrement total sound length.
while ( slen ) // While still audio data to decompress....
{
sample = *source++; // Get sample.
if ( sample & RESYNC ) // Is it a resync byte?
{
*dest++ = prev = (sample&0x7F)<<1; // Store resync byte.
slen--; // Decrement output sample length.
}
else
{
if ( sample & SQLCH ) // Is it a squelch byte?
{
count = sample&SQUELCHCNT; // And off the number of squelch bytes
slen-=count; // Decrement total samples remaining count.
for (; count; count--) *dest++ = prev; // send the repeated data out..
}
else // Must be a delta modulate byte!!
{
bits = sample&DELTAMOD; // Delta mod resolution.
plier = sample&MULTIPLIER;
base = trans+plier*16; // Compute base address to multiplier table.
slen-=frame; // Pulling one frame out.
switch ( bits )
{
case ONEBIT:
bytes = frame/8; // 8 samples per byte.
down = base[7]; // Go down 1 bit.
up = base[8]; // Go up 1 bit.
for (;bytes;bytes--)
{
sample = *source++;
for(mask=0x80; mask; mask=mask>>1)
{
if ( sample & mask )
prev+=up;
else
prev+=down;
if ( prev < 0 ) prev = 0;
if ( prev > 255 ) prev = 255;
*dest++=prev;
}
}
break;
case TWOBIT:
bytes = frame/4; // 4 samples per byte.
base+=6; // Base address of two bit delta's.
for (;bytes;bytes--)
{
sample = *source++;
one = sample>>6; // Top two bits.
two = (sample>>4)&0x3; // Next two bits.
three = (sample>>2)&0x3; // New two.
four = sample&0x3; // last two.
prev+=base[one];
if ( prev < 0 ) prev = 0;
if ( prev > 255 ) prev = 255;
*dest++=prev;
prev+=base[two];
if ( prev < 0 ) prev = 0;
if ( prev > 255 ) prev = 255;
*dest++=prev;
prev+=base[three];
if ( prev < 0 ) prev = 0;
if ( prev > 255 ) prev = 255;
*dest++=prev;
prev+=base[four];
if ( prev < 0 ) prev = 0;
if ( prev > 255 ) prev = 255;
*dest++=prev;
}
break;
case FOURBIT:
bytes = frame/2;
for (;bytes;bytes--)
{
sample = *source++;
up = sample>>4; // High nibble.
down = sample&0x0F; // Low nibble.
prev+=base[up];
if ( prev < 0 ) prev = 0;
if ( prev > 255 ) prev = 255;
*dest++=prev;
prev+=base[down];
if ( prev < 0 ) prev = 0;
if ( prev > 255 ) prev = 255;
*dest++=prev;
}
break;
}
}
}
}
return( length );
}
// GetFreq will report the playback frequency of a particular ACOMP data
// file.
unsigned int far GetFreq(unsigned char far *sound)
{
return( Get8086word(sound+2) );
}
// This is used to make certain this C code is compatible when compiled on
// a 68000 based machine. (Which it has been done and tested on.)
short Get8086word(unsigned char far *temp)
{
short low,high;
low = *temp++;
high = *temp;
return( low + high*256 );
}